package com.flow.framework.persistence.parser;

import com.baomidou.mybatisplus.core.parser.AbstractJsqlParser;
import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.util.verify.VerifyUtil;
import com.flow.framework.core.holder.SystemVersionContextHolder;
import com.flow.framework.core.properties.FrameworkCoreConfigProperties;
import com.flow.framework.persistence.constant.FrameworkPersistenceConstant;
import com.flow.framework.persistence.properties.FrameworkPersistenceConfigProperties;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.update.Update;

import java.util.List;

/**
 * 系统版本号sql解析器，只有在插入和更新时生效
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/4/4
 */
@Slf4j
@AllArgsConstructor
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class SystemVersionSqlParser extends AbstractJsqlParser {

    private final FrameworkPersistenceConfigProperties frameworkPersistenceConfigProperties;

    private final FrameworkCoreConfigProperties frameworkCoreConfigProperties;

    private Expression getSystemVersion() {
        Long systemVersion = SystemVersionContextHolder.getCurrentSystemVersion();
        if (null == systemVersion) {
            log.error("system version is null");
            throw new CheckedException(SystemErrorCode.PARAMS_ERROR);
        }
        return new LongValue(systemVersion);
    }

    /**
     * select 语句处理
     */
    @Override
    public void processSelectBody(SelectBody selectBody) {

    }

    /**
     * insert 语句处理
     */
    @Override
    public void processInsert(Insert insert) {
        boolean enableEnvCodeSupport = frameworkCoreConfigProperties.isEnableEnvCodeSupport();
        if (!enableEnvCodeSupport) {
            return;
        }
        List<String> ignoreSystemVersionTableNames = frameworkPersistenceConfigProperties.getIgnoreSystemVersionTableNames();
        if (!VerifyUtil.isEmpty(ignoreSystemVersionTableNames)
                && !ignoreSystemVersionTableNames.contains(insert.getTable().getName())) {
            // 过滤退出执行
            return;
        }
        insert.getColumns().add(new Column(FrameworkPersistenceConstant.SYSTEM_VERSION_COLUMN_NAME));
        ItemsList itemsList = insert.getItemsList();
        if (itemsList instanceof MultiExpressionList) {
            ((MultiExpressionList) itemsList).getExprList().forEach(el -> el.getExpressions().add(getSystemVersion()));
        } else {
            ((ExpressionList) insert.getItemsList()).getExpressions().add(getSystemVersion());
        }
    }

    /**
     * update 语句处理
     */
    @Override
    public void processUpdate(Update update) {
        boolean enableEnvCodeSupport = frameworkCoreConfigProperties.isEnableEnvCodeSupport();
        if (!enableEnvCodeSupport) {
            return;
        }
        update.getColumns().add(new Column(FrameworkPersistenceConstant.SYSTEM_VERSION_COLUMN_NAME));
        update.getExpressions().add(getSystemVersion());
    }

    /**
     * delete 语句处理
     */
    @Override
    public void processDelete(Delete delete) {

    }
}
